package utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class DataMiner {
	private final static Logger LOGGER = Logger.getLogger(DataMiner.class
			.getName());
	Map<String, Integer> colorAmountMap;
	private Integer pageNr;
	private String regexTagContent;
	private String regexValContent;
	private String regexColorContent;
	private String regexPagesContent;
	private String urlPart;
	
	public DataMiner() {
		colorAmountMap = new TreeMap<>();
	}
	/**
	 * Gets a string of the HTML code of the "ipString" html page
	 * 
	 * @param ipString
	 *            - valid IP address with HTTP port(80) enabled
	 * @return String containing page source code
	 * @throws IOException
	 *             - (BufferReader)
	 */
	private String getUrlSource(String ipString) throws IOException  {
		URL ip = new URL(ipString);
		URLConnection ipConn = ip.openConnection();
		BufferedReader in = new BufferedReader(new InputStreamReader(
				ipConn.getInputStream(), "UTF-8"));
		String inputLine;
		StringBuilder a = new StringBuilder();
		while ((inputLine = in.readLine()) != null)
			a.append(inputLine);
		in.close();

		return a.toString();
	}
	
	/**
	 * @param pageNr the pageNr to set
	 */
	public void setPageNr(Integer pageNr) {
		this.pageNr = pageNr;
	}
	/**
	 * 
	 * @param context
	 * @return
	 */
	private void findNrOfPages(String context) { // Total Sides
		int nrOfPages = 0;
	
		Pattern patternColorContent = Pattern.compile(regexPagesContent);
		Matcher matcherColorContent = patternColorContent.matcher(context);

		if(matcherColorContent.find()){		
			LOGGER.log(Level.INFO, " ___ MATCH ___ " + matcherColorContent.group());
			LOGGER.log(Level.INFO, " ___ MATCH ___ " + matcherColorContent.group(4));
			LOGGER.log(Level.INFO, " ___ MATCH ___ " + matcherColorContent.group(3)+ matcherColorContent.group(4));
			nrOfPages = Integer.parseInt(matcherColorContent.group(4));
		}
		setPageNr(nrOfPages);
	}

	/**
	 * Gets values from 'context' param | Printer cartiges
	 * 
	 * @param String
	 *            context - gets the page to be parsed
	 */
	public List<Integer> findCartegisProcentr(String context) {
		List<Integer> vals = new ArrayList<>();
		
		regexValContent = "\\d{2}|-{2}";
		Pattern patternTagContent = Pattern.compile(regexTagContent);
		Matcher matcherTagContent = patternTagContent.matcher(context);

		Pattern patternValContent = Pattern.compile(regexValContent);
		while (matcherTagContent.find()) {
			Matcher matcherValContent = patternValContent
					.matcher(matcherTagContent.group(2));
			matcherValContent.find();
 			try {
				vals.add(Integer.parseInt(matcherValContent.group()));
			} catch (Exception e) {
				vals.add(0);
			}
		}
		return vals;
	}

	/**
	 * Build the color-value pair mined from the printer
	 * 
	 * @param ipString
	 *            (destination IP, for http protocol enabled device)
	 * @throws IOException
	 */
	public void buildCartigesAndValue(String ipString) throws IOException  {
		LOGGER.log(Level.INFO, "Starting mining over IP " + ipString);
		String context = getUrlSource(ipString);
		 
		urlPart = "/info_colorUsageJobLog.html?tab=Status&menu=ColorUsageLog";
		if (context.contains("HP Color LaserJet CP2025dn") || context.contains("HP Color LaserJet CM2320nf MFP")) {
			LOGGER.log(Level.INFO, "PRINTER TYPE ======= HP Color LaserJet CP2025dn");
			regexColorContent = "\\w+\\W{1}Cartridge (?<!Printer)";
			regexTagContent = "(<td{1}>)([^<]{1}[^.{20}][^&nbsp;&nbsp;].*?)(</td>)";
		}
		else if (context.contains("HP LaserJet 400 color M451dw")){
			LOGGER.log(Level.INFO, "PRINTER TYPE ======= HP LaserJet 400 color M451dw");
			regexColorContent = "\\w+\\W{1}Cartridge (?<!Printer)";
			regexTagContent = "(<table\\s+class\\s*=\\s*\"\\s*width100\\s*\"s*>\\s*<tr>\\s*<td>.*?)(</td>\\s*<td\\s+class\\s*=\\s*\"\\s*alignRight\\s+valignTop\\s*\"\\s*>.*?</td>)  ";
		}
	
		List<Integer> vals = findCartegisProcentr(context);
		List<String> colors = findCartigesColor(context);
		for (int i = 0; i < colors.size(); i++) {
			if (colors.get(i).contains("Printer")) {
				continue;
			}
			addNewColorVal(colors.get(i), vals.get(i));
		}
		LOGGER.log(Level.INFO, "Stopping sucessfully ---- MAP ---- " + this.colorAmountMap.toString());
	}
	
	/**
	 * Gets colors from 'context' param | Printer cartiges
	 * 
	 * @param String
	 *            context - gets the page to be parsed
	 */
	public List<String> findCartigesColor(String context) {
		List<String> colors = new ArrayList<>();

		Pattern patternColorContent = Pattern.compile(regexColorContent);
		Matcher matcherColorContent = patternColorContent.matcher(context);
		while (matcherColorContent.find()) {
			colors.add(matcherColorContent.group());
		}
		return colors;
	}

	/**
	 * Gets the number of pages from the HTML device page
	 * 
	 * @param ipString
	 *            - IP string
	 * @throws IOException
	 */
	public void buildNrOfPagesToday(String ipString) throws IOException {
		LOGGER.log(Level.INFO, "Starting Looking for Number of Pages over IP "
				+ ipString);
		String context = getUrlSource(ipString + urlPart);
		if (context.contains("HP Color LaserJet CP2025dn") || context.contains("HP Color LaserJet CM2320nf MFP")) {
			urlPart = "/info_colorUsageJobLog.html?tab=Status&menu=ColorUsageLog";
			regexPagesContent ="(.{23})(Total Sides:)(.{31,90})(\\d{2,})";
		}
		else if (context.contains("HP LaserJet 400 color M451dw")){
			urlPart = "/info_colorUsageJobLog.html?tab=Home&menu=ColorUsageLog";
			regexPagesContent ="(.{23})(Total Sheets:)(.{31,90})([0-9]{2,4})";
			
		}
		
		findNrOfPages(context);
		LOGGER.log(Level.INFO,
				"Stopping sucessfully  ----  total todays nr of pages: " + this.getNrOfPages());
	}


	/**
	 * Insert value for spedcified key, if exists updates else inserts
	 * 
	 * @param key
	 *            - String color
	 * @param value
	 *            - Integer color
	 */
	private void addNewColorVal(String key, Integer value) {
		if (colorAmountMap.containsKey(key)) {
			colorAmountMap.remove(key);
		}
		this.colorAmountMap.put(key, value);
	}

	public Map<String, Integer> getColorValues() {
		return this.colorAmountMap;
	}
	
	public Integer getNrOfPages() {
		return this.pageNr;
	}

	/**
	 * Packs to a string printed page quantity and cartiges percents for
	 * TechResource status
	 * 
	 * @return String containing printedPagesToday + cartiges percentes
	 */

	public String getUrlSourceTest(String ipString) throws IOException {
		return this.getUrlSource(ipString);
	}

	public void addNewColorValTest(String key, Integer value) {
		this.colorAmountMap.put(key, value);
	}
	
//	public static void main(String argc[]){
//		DataMiner dm = new DataMiner();
//		String p = "http://";
//		try {
//			dm = new DataMiner();
//			dm.buildCartigesAndValue(p+"10.130.2.64");
//			dm.buildNrOfPagesToday(p+"10.130.2.64");
//			dm = new DataMiner();
//			dm.buildCartigesAndValue(p+"10.130.3.194");
//			dm.buildNrOfPagesToday(p+"10.130.3.194");
//			dm = new DataMiner();
//			dm.buildCartigesAndValue(p+"10.130.3.154");
//			dm.buildNrOfPagesToday(p+"10.130.3.154");
//			
//		} catch (Exception e) {
//			System.out.println(" EXCEPTION : "  + e);
//		}
//	}
}
